
-- Program: LuaPlayground.lua
-- Author: Mikael Kindborg
-- Description: Lua browser/editor

----------------------------------------------
-- Highjack the keydown function            --
----------------------------------------------

-- The global application state.
GApplicationState = "RunningApplicationCode"

-- Create and call a closure that sets up a custom 
-- keydown functon. We "highjack" the system onKeyDown 
-- function with our own function. This prevents the 
-- programmer from blocking/replacing the exit on back 
-- behaviour.
System.onKeyDown = (function()
  -- "Instance variable" that refers to the user set
  -- keydown function.
  local userKeyDownFun = nil

  -- Set the keydown function that exits on back and
  -- calls the user set keydown function.
  System.onKeyDown(function(keyCode, nativeKeyCode)
    -- Always exit on MAK-BACK so that the user always
    -- can quit the program, even if "evil" code tries
    -- to prevent it.
    if MAK_BACK == keyCode then
      if "RunningUserCode" == GApplicationState then
        maWidgetScreenShow(TabScreen)
        GApplicationState = "RunningApplicationCode"
      else
        maExit(0)
      end
    end

    -- If there is a user set keydown function we call it.
    if nil ~= userKeyDownFun then
      userKeyDownFun(keyCode, nativeKeyCode)
    end
  end)

  -- This is our custom onKeyDown function.
  return function(keyDownFun)
    userKeyDownFun = keyDownFun
  end
end)()

----------------------------------------------
-- Support for simple widget event handling --
----------------------------------------------

function WidgetEventGetType(widgetEvent)
  return SysBufferGetInt(widgetEvent, 0)
end

function WidgetEventGetHandle(widgetEvent)
  return SysBufferGetInt(widgetEvent, 1)
end
  
function WidgetEventGetIntParam(widgetEvent)
  return SysBufferGetInt(widgetEvent, 2)
end

-- Create event handler object.
EventHandler = (function()
  -- The event handler object.
  self = {}
  
  -- Table that contains widget -> function pairs.
  local widgetEventTable = {}

  -- Add an event function to a widget.
  self.addWidgetEvent = function(widget, eventFunction)
    widgetEventTable[widget] = eventFunction
  end

  -- Set event function.
  System.onCustomEvent(function(event)
    -- Is this a widget event?
    if EVENT_TYPE_WIDGET == SysEventGetType(event) then
      -- Get the widget event.
      local widgetEvent = SysEventGetData(event)
      -- Get the widget handle of the event.
      local widget = WidgetEventGetHandle(widgetEvent)
      -- Is there a function registered for this widget?
      if nil ~= widgetEventTable[widget] then 
        -- Yes there is, call the function.
        widgetEventTable[widget](widgetEvent)
      end
    end
  end)

  return self

end)()

----------------------------------------------
-- Application code                         --
----------------------------------------------

-- Helper function for parsing out the Lua code in a text.
-- The code is within "-- MOBILELUA BEGIN --" and 
-- "-- MOBILELUA END --" tags.
function ParseTextWithEmbeddedLuaCode(text)
  local startTag = "-- MOBILELUA BEGIN"
  local stopTag = "-- MOBILELUA END"
  local start = text:find(startTag, 0)
  local stop = text:find(stopTag, start)
  if nil == start or nil == stop then
    return nil
  else
    local code = text:sub(start, stop + stopTag:len())
    return code
  end
end

-- Create the screen that shows the list of program urls.
function CreateListScreen()
  local screen = maWidgetCreate("Screen")
  maWidgetSetProperty(screen, "title", "Programs")

  local listView = maWidgetCreate("ListView")
  maWidgetSetProperty(listView, "width", "-1")
  maWidgetSetProperty(listView, "height", "-1")
	
  EventHandler.addWidgetEvent(listView, function(widgetEvent)
    --if MAW_EVENT_CLICKED == WidgetEventGetType(widgetEvent) then
      maMessageBox(
        "Widget clicked", 
        "Clicked item " .. WidgetEventGetIntParam(widgetEvent))
    --end
  end)
  
  -- TODO: Read saved links from store.
  -- For now, add a couple of hardcoded urls.
  -- maWidgetSet/GetUserData would be nice to have...
  -- Would also enable event callbacks in C.
  
  local listItem = maWidgetCreate("ListViewItem")
  maWidgetSetProperty(
    listItem, 
    "text", 
    "http://code.google.com/p/mobilelua/")
  maWidgetAddChild(listView, listItem)

  local listItem = maWidgetCreate("ListViewItem")
  maWidgetSetProperty(
    listItem, 
    "text", 
    "http://openplay.se/MobileLua/Foo.lua")
  maWidgetAddChild(listView, listItem)

  maWidgetAddChild(screen, listView)

  return screen
end

function CreateOpenScreen()
  local screen = maWidgetCreate("Screen")
  maWidgetSetProperty(screen, "title", "Open")

  local layout = maWidgetCreate("VerticalLayout")
  maWidgetSetProperty(layout, "width", "-1")
  maWidgetSetProperty(layout, "height", "-1")

  local urlEditBox = maWidgetCreate("EditBox")
  maWidgetSetProperty(urlEditBox, "width", "-1")
  maWidgetSetProperty(urlEditBox, "height", "-2")
  maWidgetSetProperty(urlEditBox, "text", "http://code.google.com/p/mobilelua/")

  local loadButton = maWidgetCreate("Button")
  maWidgetSetProperty(loadButton, "width", "-1")
  maWidgetSetProperty(loadButton, "height", "-2")
  maWidgetSetProperty(loadButton, "text", "Run program")

  EventHandler.addWidgetEvent(loadButton, function(widgetEvent)
    -- Get the url string.
    maWidgetSetProperty(urlEditBox, "showKeyboard", "false")
    local urlBuffer = SysBufferCreate(256)
    maWidgetGetProperty(urlEditBox, "text", urlBuffer, 256)
    local url = SysBufferToString(urlBuffer)
    SysBufferDelete(urlBuffer)

    -- Function called on download complete.
    local loadAndRunScriptFun = function(data)
      if nil == data then
        maMessageBox("Could not download code", url)
      else
        -- Parse out the script.
        local code = ParseTextWithEmbeddedLuaCode(data)
        if nil == code then
          -- Assume it is a Lua program without tags.
          code = data
        end
        print("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@")
        print(code)
        -- Parse the code.
        local fun, errorMessage = loadstring(code)
        if nil == fun then
          maMessageBox("Lua Error", errorMessage)
        else
          -- Hide the native UI and show the MoSync drawing screen.
          maWidgetScreenShow(MAW_CONSTANT_MOSYNC_SCREEN_HANDLE)
          -- Evaluate the code.
          fun()
          GApplicationState = "RunningUserCode"
        end
      end
    end
    -- Start the download.
    System.downloadText(url, loadAndRunScriptFun)
  end)

  maWidgetAddChild(layout, urlEditBox)
  maWidgetAddChild(layout, loadButton)
  maWidgetAddChild(screen, layout)
  
  return screen
end

function CreateEditScreen()
  local screen = maWidgetCreate("Screen")
  maWidgetSetProperty(screen, "title", "Code")

  local layout = maWidgetCreate("VerticalLayout")
  maWidgetSetProperty(layout, "width", "-1")
  maWidgetSetProperty(layout, "height", "-1")

  local runButton = maWidgetCreate("Button")
  maWidgetSetProperty(runButton, "width", "-1")
  maWidgetSetProperty(runButton, "height", "-2")
  maWidgetSetProperty(runButton, "text", "Run program")

  local codeEditBox = maWidgetCreate("EditBox")
  maWidgetSetProperty(codeEditBox, "width", "-1")
  maWidgetSetProperty(codeEditBox, "height", "-1")
  maWidgetSetProperty(codeEditBox, "text",
    'Screen.setColor(255, 255, 0)\n'..
    'Screen.fillRect(0, 0, Screen.getWidth(), Screen.getHeight())\n'..
    'Screen.update()')
  EventHandler.addWidgetEvent(runButton, function(widgetEvent)
    -- Get the url string.
    maWidgetSetProperty(codeEditBox, "showKeyboard", "false")
    local codeBuffer = SysBufferCreate(4096)
    maWidgetGetProperty(codeEditBox, "text", codeBuffer, 4096)
    local code = SysBufferToString(codeBuffer)
    SysBufferDelete(codeBuffer)

    print("------@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@")
    print(code)
    -- Parse the code.
    local fun, errorMessage = loadstring(code)
    if nil == fun then
      maMessageBox("Lua Error", errorMessage)
    else
      -- Hide the native UI and show the MoSync drawing screen.
      maWidgetScreenShow(MAW_CONSTANT_MOSYNC_SCREEN_HANDLE)
      -- Evaluate the code.
      fun()
      GApplicationState = "RunningUserCode"
    end
  end)

  maWidgetAddChild(layout, runButton)
  maWidgetAddChild(layout, codeEditBox)
  maWidgetAddChild(screen, layout)
  
  return screen
end

function CreateHelpScreen()
  local screen = maWidgetCreate("Screen")
  maWidgetSetProperty(screen, "title", "Help" )
  --maWidgetSetPropertyInt(screen, "icon", R_TV)

  local webView = maWidgetCreate("WebView")
  maWidgetSetProperty(webView, "width", "-1")
  maWidgetSetProperty(webView, "height", "-1")

  maWidgetSetProperty(webView, "url", "http://code.google.com/p/mobilelua/")
  maWidgetAddChild(screen, webView)

  return screen
end

-- Create screens.
TabScreen = maWidgetCreate("TabScreen")
ListScreen = CreateListScreen()
maWidgetAddChild(TabScreen, ListScreen)
OpenScreen = CreateOpenScreen()
maWidgetAddChild(TabScreen, OpenScreen)
EditScreen = CreateEditScreen()
maWidgetAddChild(TabScreen, EditScreen)
HelpScreen = CreateHelpScreen()
maWidgetAddChild(TabScreen, HelpScreen)

-- Open main screen.
maWidgetScreenShow(TabScreen)

-- print("Hello")
